package util;

import static util.MatrixOperationsF.add;
import static util.MatrixOperationsF.multiply;

/**
 * A transformation is represented by a float[][] applying the transformation is
 * the same as matrix multiplication
 * 
 */
public final class Transformations {
	private static float abs(float x) {
		return Math.abs(x);
	}

	private static float cos(float x) {
		return (float) Math.cos(x);
	}

	private static float sin(float x) {
		return (float) Math.sin(x);
	}

	public static float[][] transform3DScaling(float xscale, float yscale,
			float zscale) {
		float[][] rv = ones(4);
		rv[0][0] *= xscale;
		rv[1][1] *= yscale;
		rv[2][2] *= zscale;
		return rv;
	}

	/**
	 * an [ixi] Matrix with ones on the diagonal
	 */
	public static float[][] ones(int i) {
		float[][] rv = new float[i][i];
		for (int j = 0; j < rv.length; j++) {
			for (int j2 = 0; j2 < rv.length; j2++) {
				rv[j][j2] = 0;
				if (j == j2)
					rv[j][j2] = 1;
			}
		}
		return rv;
	}

	public static float[][] transform3DRoationX(float radians) {
		float[][] rv = ones(4);
		rv[1][1] = cos(radians);
		rv[1][2] = sin(radians);
		rv[2][1] = -sin(radians);
		rv[2][2] = cos(radians);
		return rv;
	}

	public static float[][] transform3DTranslate(float[] vertex) {
		float[][] rv = ones(4);
		rv[0][3] = vertex[0];
		rv[1][3] = vertex[1];
		rv[2][3] = vertex[2];

		return rv;
	}

	public static float[][] transform3DRoationY(float radians) {
		float[][] rv = ones(4);

		return rv;
	}

	/**
	 * Creates an orthographic projection from the {lbn,rtf} box to the CCV of
	 * [-1,1]^3, this assumes the lbn and rtf are arrays of length 3 , longer
	 * arrays will not cause problems as long as the first 3 define the box.
	 */
	public static float[][] generalOrthographicProjection(float[] lbn,
			float[] rtf) {
		return multiply(
				transform3DScaling(2 / (abs(lbn[0] - rtf[0])), 2 / (abs(lbn[1]
						- rtf[1])), 2 / (abs(lbn[2] - rtf[2]))),
				transform3DTranslate(multiply(add(lbn, rtf), -.5f)));
	}

	public static float[][] drawCanonical(int xmax, int ymax) {
		float[][] rv = ones(4);
		rv[0][0] = xmax / 2;
		rv[0][3] = (xmax - 1) / 2;
		rv[1][1] = (ymax) / 2;
		rv[1][3] = (ymax - 1) / 2;
		return rv;
	}

	public static float[][] transform3DRoationZ(float radians) {
		float[][] rv = ones(4);

		return rv;
	}
}
